# -*- coding:   utf-8 -*-

import re
import requests



class Spider:
    """
    迅雷网盘链接保存
    """
    get_captcha_get_token = {
        "client_id": "Xqp0kJBXWhwaTpB6",
        "action": "GET:CAPTCHA_TOKEN",
        "device_id": "221ac876844d581e435fa51bec5249c3",
        "captcha_token": "ck0.R2Ysc3z84yE0cHMY3jftzu95cz8Up9mNVNJLI7cph-aDXzLrq-a-jZ0kZOnSvWV7B0QdGmiITcvK9qjCYbtgsdWe0HJ4dk2qspd8cCBg2dDwcrKZkxMFCtFKKEW6e6TCBdHj9MNe-AZz7eg50doFqtBWmX6GPH32iobVMW1W0Hsi0e0uIrhE4VqfvGbaLPkpwD4FSW8qFICtBKQJ1_PHdyfnFKiAFMMPBqgRLI1Pz7qYCtgpGUtnv9A143Y1dh9ZBLfyPYUtSKB68_rbS7Aaaw_BF6HCSshR2Z-QH3Xa__WF2PgGUJJUYNpBUnDlxvq5kCnQb4llwwu-FctiGJIewvcMxTICbRCf30SNuu8HjOAxRXidriAxqDXqW-J2eeKA.ClMIuI77-uYuEhBYcXAwa0pCWFdod2FUcEI2GgYxLjI1LjUiDnBhbi54dW5sZWkuY29tKiAyMjFhYzg3Njg0NGQ1ODFlNDM1ZmE1MWJlYzUyNDljMxKAAVpJQuyQcSiTaHlnY8E0FsG7lxX_8kis-OCrHdcvxQSH2bykIIlFe8qO8saKaIwjdkaqx1riH2lTU_ml2xYpoy6xVCTmgc9W2XZ2NxyHdOfv0KX4Riv7tAu8qUXL5m_xingnjhdAQN38mHZ0bT2DqcLaWYZSI8BTx8ik47oZffGI",
        "meta": {
            "package_name": "pan.xunlei.com",
            "client_version": "1.25.5",
            "captcha_sign": "1.40577908495706a66b64c0d83234a663",
            "timestamp": "1608186600907",
            "user_id": "0"
        }
    }


    def __init__(self, account,password,share_id, pass_code):




        self.account = account
        self.mobile = '+86 '+self.account
        self.password = password

        self.get_captcha_login = {"client_id": "XW5SkOhLDjnOZP7J",
                                  "action": "POST:/v1/auth/signin",
                                  "device_id": "3a13f183b33e46fba755ad0aca2743f7",
                                  "captcha_token": "ck0.-3pKd8MAvut9bHV-xsafkmI-cv47U6krUDZJ00NmnU2Bs3RsH3hfpAsbeYpImRlItNYhijHgNXgsiFa2Mj8wGX6ZANNXl0gJZ6Ur6UwcrVdRWxrcQ9TirOCbZ28obWX5fm84MkkKWQ2dCSE-qWNO5F-6vTComgsPDDDjZezvJZYRf3s0ZCZAd7DWYzp6Tr-nnLfwkWUNqngIUI-5hys4mL4TsRESk6jtxFT6N100eqqS67A18dy0h6AXPTj1_n--",
                                  "meta": {"phone_number": self.mobile, "username": self.mobile}}


        self.share_id = share_id  # 分享链接s后面的字符串
        self.pass_code = pass_code  # 提取码
        self.captcha_init_url = 'https://xluser-ssl.xunlei.com/v1/shield/captcha/init'
        self.captcha_token = ''
        self.login_url = 'https://xluser-ssl.xunlei.com/v1/auth/signin?captcha_token={captcha_token}'
        self.token_type = ''
        self.access_token = ''
        self.refresh_token = ''
        self.expires_in = ''
        self.user_id = 0

        # 输入提取码
        self.check_password_url = 'https://api-pan.xunlei.com/drive/v1/share?share_id={share_id}&pass_code={pass_code}&limit=100&pass_code_token=lXQoQtM3UCtFfiGAvqpQEEd6WGrAlA9EurBkSkuCfvQ1ZupCLGXnsVZ5eJROaTzsyPu3J7g9fEisY7Qp0xJjxg%3D%3D&page_token='
        self.files = []

        """
        {"client_id":"Xqp0kJBXWhwaTpB6",
        "state":"state-gjpjz2g2s7w",
        "redirect_uri":"https://pan.xunlei.com/blank/?id=VMOdnB8KZV89GFRK9fZ71NAwA1&sso_sign_in_in_iframe=",
        "response_type":"code",
        "sign_out_uri":"https://pan.xunlei.com/s/VMOdnB8KZV89GFRK9fZ71NAwA1?sso_sign_out=",
        "scope":"profile+offline+pan+sso+user",
        "code_challenge":"6KxFwLCeNzgKv_qAa-AylIYcyWJxjalYy3w_8VLjyOo","code_challenge_method":"S256"}
        """
        self.pass_code_token = 'https://xluser-ssl.xunlei.com/v1/user/authorize'

        self.user_authorize_url = 'https://xluser-ssl.xunlei.com/v1/user/authorize'
        self.user_authorize_data = {}

        # 获取转存权限token以便使用转存使用，和登录access-token无关
        self.auth_token_url = 'https://xluser-ssl.xunlei.com/v1/auth/token'
        self.auth_access_token = ''

        # 转存
        self.restore_url = 'https://api-pan.xunlei.com/drive/v1/share/restore'

        self.session = requests.session()

        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
        }

    def share_init(self, data):
        """
        登录前初始化
        :param data:
        :return:
        """
        self.headers.update({'Referer': 'https://i.xunlei.com/'})
        response = self.session.post(self.captcha_init_url, json=data, headers=self.headers)
        if response.status_code == 200:
            result = response.json()
            self.captcha_token = result['captcha_token']
            return True, '初始化成功'
        return False, '初始化失败'

    def login(self):
        """
        登录
        :return:
        """
        account = self.mobile
        status, msg = self.share_init(self.get_captcha_login)
        if not status:
            return 101, '初始化登录票据失败'
        login_url = self.login_url.format(captcha_token=self.captcha_token)
        payload = {"username": account, "password": self.password, "client_id": "XW5SkOhLDjnOZP7J"}
        self.headers.update({'Referer': 'https://pan.xunlei.com/'})
        response = self.session.post(login_url, json=payload, headers=self.headers)
        if response.status_code == 200:
            token_data = response.json()
            self.token_type = token_data['token_type']
            self.access_token = token_data['access_token']
            self.refresh_token = token_data['refresh_token']
            self.expires_in = token_data['expires_in']
            self.user_id = token_data['user_id']
            return 200, '登录成功'
        return 201, '登录失败'

    def share(self):
        """
        校验提取码
        :return:
        """
        status, msg = self.share_init(self.get_captcha_get_token)
        if not status:
            return 101, '初始化校验提取码票据失败'
        self.headers.update({'Referer': 'https://pan.xunlei.com/'})
        self.headers.update({
            'x-captcha-token': self.captcha_token,
            'x-client-id': 'Xqp0kJBXWhwaTpB6',
            'x-device-id': '221ac876844d581e435fa51bec5249c3',
        })
        share_url = self.check_password_url.format(share_id=self.share_id, pass_code=self.pass_code)

        response = self.session.get(share_url, headers=self.headers)
        if response.status_code == 200:
            result = response.json()
            if result:
                share_status = result['share_status']
                if share_status != 'OK':
                    return 301, share_status
                self.files = result['files']
                self.pass_code_token = result['pass_code_token']
                if not self.files:
                    return 303, '未获取到文件信息'
                return 200, '提取码校验成功'
        return 302, '输入提取码异常'

    def user_authorize(self):
        """
        获取code
        :return:
        """
        self.headers.update({"Referer": "https://i.xunlei.com/"})
        self.headers.update({"Authorization": "Bearer " + self.access_token})
        # request
        payload = {"client_id": "Xqp0kJBXWhwaTpB6",
                   "state": "state-gjpjz2g2s7w",
                   "redirect_uri": "https://pan.xunlei.com/blank/?id=" + self.share_id + "&sso_sign_in_in_iframe=",
                   "response_type": "code",
                   "sign_out_uri": "https://pan.xunlei.com/s/" + self.share_id + "?sso_sign_out=",
                   "scope": "profile+offline+pan+sso+user",
                   "code_challenge": "6KxFwLCeNzgKv_qAa-AylIYcyWJxjalYy3w_8VLjyOo",
                   "code_challenge_method": "S256"
                   }
        response = self.session.post(self.user_authorize_url, json=payload, headers=self.headers)
        if response.status_code == 200 and response.text:
            self.user_authorize_data = response.json()
            return 200, '获取user-auth票据成功'
        return 401, '获取user-auth票据未知异常'

    def auth_token(self):
        """
        获取转存需要的token
        :return:
        """
        self.headers.update({"Referer": "https://pan.xunlei.com/",
                             "x-protocol-version": "301",
                             "x-sdk-version": "3.2.18"
                             })
        if self.user_authorize_data:
            data = self.user_authorize_data
            payload = {
                'code': data.get('code'),
                "grant_type": "authorization_code", "code_verifier": "CsJBssEyifojOL6U5XdEeuafNgtAuKF9",
                "redirect_uri": "https://pan.xunlei.com/blank/?id=" + self.share_id + "&sso_sign_in_in_iframe=",
                "client_id": "Xqp0kJBXWhwaTpB6"
            }
            response = self.session.post(self.auth_token_url, json=payload, headers=self.headers)
            if response.status_code == 200 and response.text:
                result = response.json()
                self.auth_access_token = result['access_token']
                return 200, '获取转存auth_access_token成功'
        return 501, '获取转存auth_access_token未知异常'


    def restore(self):
        """
        保存文件
        :return:
        """
        files_data = self.files
        get_restore_token = {"client_id": "Xqp0kJBXWhwaTpB6", "action": "GET:CAPTCHA_TOKEN",
                             "device_id": "221ac876844d581e435fa51bec5249c3",
                             "captcha_token": "ck0.J264ICRjGBcK17BJmCRUVKjE_cFu3kOMnJSxDYM8X7GOfW2icIJTAezlF_jt2gg54-9ag5KIGHNc6eK8C-UXV5M12Lq9NoAvTboVd6Zgz7CzjrGT-5a3IxsHFaAWpzzDS_AdBWkPSkbjPdGjy906wN7v79ghekuHjUJ566HOlhpI52rFkax_fcaEjAtmFCPAc8qtQ4XUPPkPzzf_nAhQAIVbLk9Dn5uQ692SvwaWzrpCIueuK2fYmqG8nq0OqttPyh4PU_H7uqQzGDrecBO5fhzGY-1dHoWhskxh_OZJfLwGaQKtQOBzeMJG6VwLWKj3aLiqX9nNM6yTqRISgnUQXQKKFSQ9VtvuJnKtxGG7cPg7esvYAAkGtfyqLq0z4NKn.ClMIrbKZ_eYuEhBYcXAwa0pCWFdod2FUcEI2GgYxLjI1LjUiDnBhbi54dW5sZWkuY29tKiAyMjFhYzg3Njg0NGQ1ODFlNDM1ZmE1MWJlYzUyNDljMxKAAY3cHg8jsbuBc3Qc_2ZeE3dCuC9Tg0gnQCxnWPKH3WhUIrSP8DJZuIY6Lh38be0pkUPWwBnzZUs_mhPwXPQ_C_yC6UiYSpCeIk34x15dSJ6OqEqOAWUtI8yMIlTyau6g2N8wRtMDVou-Ea0CVMtgpQ4IKTqwLLdvB5IVItmgxO3W",
                             "meta": {"package_name": "pan.xunlei.com", "client_version": "1.25.5",
                                      "captcha_sign": "1.1d75d0674c519a5dd6b05c7365da2784",
                                      "timestamp": "1608191198734",
                                      "user_id": self.user_id}}
        status, msg = self.share_init(get_restore_token)
        if not status:
            return 101, '初始化转存文件票据失败'
        restore_url = self.restore_url
        file_ids = [v['id'] for v in files_data]
        file_names = [v['name'] for v in files_data]

        payload = {
            "share_id": self.share_id,
            'pass_code_token': self.pass_code_token,
            "ancestor_ids": [],
            "file_ids": file_ids,
        }
        self.headers.update({
            'Authorization': 'Bearer ' + self.auth_access_token,
            'x-device-id': '221ac876844d581e435fa51bec5249c3',
            'Referer': 'https://pan.xunlei.com/',
            'x-captcha-token': self.captcha_token,
            })
        response = self.session.post(restore_url, json=payload, headers=self.headers)
        if response.status_code == 200 and response.text:
            result = response.json()
            if result.get('restore_status') == 'RESTORE_COMPLETE':
                return 200, file_names
        return 601, '转存文件未知异常'


def save_file(account,password,uri, pass_code):
    spider = Spider(account,password,uri, pass_code)
    # 登录
    status, msg = spider.login()
    print('login-'+msg)
    if status != 200:
        return False, msg
    # 校验提取码
    status, msg = spider.share()
    print('share-' + msg)
    if status != 200:
        return False, msg
    # 获取code
    status, msg = spider.user_authorize()
    print('user_auth-' + msg)
    if status != 200:
        return False, msg
    # 获取转存token
    status, msg = spider.auth_token()
    print('auth_token-' + msg)
    if status != 200:
        return False, msg
    # 转存
    status, msg = spider.restore()
    print('restore-' + msg)
    if status != 200:
        return False, msg
    return True, msg


#迅雷网盘分享链接
share_url = 'https://pan.xunlei.com/s/VMWxgTGypEvkNjyUA3VN2tVGA1'
#提取码
code = 't4vz'
#获取分享链接's'后面的uri
result = re.findall('\/s\/([\s\S]*?)$', share_url)
share_id = result[0] if result else False
if not share_id:
    print('链接错误')
else:
    #登录账号目前使用的账号密码登录，且账号是手机号，其余登录账号自行抓包调试
    account = ''
    #登录密码
    password = ''
    status,msg = save_file(account,password,share_id,code)
    print(msg)